/**
 * 
 */
package com.gragra.sampling.nonproj;
import com.gragra.sampling.PopulationProbabilityAssigner;
import com.gragra.sampling.PopulationSamplingStructure;
import com.gragra.sampling.binary.ConvertSample;
import com.gragra.sampling.binary.HeadAssignmentStructure;
import com.gragra.sampling.binary.ThreadedToString;
import com.gragra.sampling.sequentialStructure.WordAndTagHolder;
import com.gragra.sequentiaDataGenerator.BaseGenerator;
/**
 * @author Christoph Teichmann
 * 23.09.2013
 */
public class MostFrequentHead implements ConvertSample
{
	/**
	 * 
	 */
	private String best = null;
	/* (non-Javadoc)
	 * @see com.gragra.sampling.binary.ConvertSample#getBest(com.gragra.sampling.PopulationSamplingStructure, com.gragra.sampling.PopulationProbabilityAssigner)
	 */
	@Override
	public String getBest(PopulationSamplingStructure str,
			PopulationProbabilityAssigner pa)
	{
		WordAndTagHolder wth = (WordAndTagHolder) str;
		return BaseGenerator.transferToString(wth)+"\r\n"+best;
	}
	/**
	 * 
	 */
	private int[][] counts = null;
	/* (non-Javadoc)
	 * @see com.gragra.sampling.binary.ConvertSample#minRisk(com.gragra.sampling.PopulationSamplingStructure, com.gragra.sampling.PopulationProbabilityAssigner)
	 */
	@Override
	public String minRisk(PopulationSamplingStructure str,
			PopulationProbabilityAssigner pa)
	{
		String s =  selectBest(counts,str);
		return convert((HeadAssignmentStructure) str,s);
	}
	/**
	 * 
	 * @param str
	 * @param s
	 * @return
	 */
	private String convert(HeadAssignmentStructure str, String s)
	{
		StringBuilder sb = new StringBuilder();
		WordAndTagHolder wth = (WordAndTagHolder) str;
		sb.append(BaseGenerator.transferToString(wth));
		sb.append("\r\n");
		sb.append(s);
		return sb.toString();
	}
	/**
	 * 
	 * @param str 
	 * @param counts2
	 * @return
	 */
	private String selectBest(int[][] c, PopulationSamplingStructure str)
	{
		StringBuilder sb = new StringBuilder();
		HeadAssignmentStructure has = (HeadAssignmentStructure) str;
		for(int i=0;i<c.length;++i)
		{
			if(i != 0)
			{sb.append(" ");}
			int head = selectBest(c[i]);
			head = head == has.getDependencyRootPosition() ? 0 : head+1;
			sb.append(head);
		}
		return sb.toString();
	}
	/**
	 * 
	 * @param is
	 * @return
	 */
	private int selectBest(int[] is)
	{
		int val = -1;
		int choice = -1;
		for(int i=0;i<is.length;++i)
		{
			int v = is[i];
			if(v > val)
			{
				val = v;
				choice = i;
			}
		}
		if(choice < 0)
		{throw new IllegalArgumentException("no valid choice for the best head.");}
		return choice;
	}
	/* (non-Javadoc)
	 * @see com.gragra.sampling.binary.ConvertSample#addSample(com.gragra.sampling.PopulationSamplingStructure)
	 */
	@Override
	public void addSample(PopulationSamplingStructure str)
	{
		HeadAssignmentStructure has = (HeadAssignmentStructure) str;
		ThreadedToString tts = (ThreadedToString) has;
		if(counts == null)
		{counts = new int[has.getLength()][has.getLength()+1];}
		for(int thread=0;thread<tts.getNumberOfThreads();++thread)
		{
			for(int i=0;i<has.getLength();++i)
			{
				int head = has.getHeadPosition(i, thread);
				counts[i][head] += 1;
			}
		}
	}
	/**
	 * 
	 * @param str
	 * @param thread 
	 * @return
	 */
	private String makeHeadString(PopulationSamplingStructure str, int thread)
	{
		HeadAssignmentStructure has = (HeadAssignmentStructure) str;
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<has.getLength();++i)
		{
			if(i!=0)
			{sb.append(" ");}
			int head = has.getHeadPosition(i, thread);
			sb.append(head == has.getDependencyRootPosition() ? 0 : head+1);
		}
		return sb.toString();
	}
	/* (non-Javadoc)
	 * @see com.gragra.sampling.binary.ConvertSample#setBest(com.gragra.sampling.PopulationSamplingStructure, int)
	 */
	@Override
	public void setBest(PopulationSamplingStructure str, int thread)
	{this.best = this.makeHeadString(str,thread);}
	/* (non-Javadoc)
	 * @see com.gragra.sampling.binary.ConvertSample#getNumberSeen(java.lang.String)
	 */
	@Override
	public double getNumberSeen(String goldTwo)
	{return 0;}
}